'use strict';

const { Service } = require('egg');
const random = require("random-js")(); //


class AnalysisService extends Service {

  /**
   * 推荐菜品分析
   * @param dishName 菜式
   * @param score 分数
   * @param comment_has 是否包含评论
   * @param recommend_count 推荐次数
   * @returns {Promise<Array>}
   */
  async recommend(dishName,score = 0,comment_has = false,recommend_count = 0) {
    const that = this;
    const promise = new Promise(function(resolve, reject) {
      that.ctx.model.Shop.find({ }, function(err, docs){
        if(err){
          reject(err)
        }else{
          resolve(docs)
        }
      }); 
    });
    let shops = await promise;
    let results = [],reduces = [];
    // calc recommend count
    const constains = ( str,strs ) => {
      let exists = false;
      for (let s of strs){
        if (s.indexOf(str) !== -1) {
          exists = true;
          break;
        }
      }
      return exists;
    }
    const calc_recommend_count = (dishName, likeList) => {
      let recommend_count_result = 0;
      for (let like of likeList){
        recommend_count_result += like && like.values && like.values.length > 0 && constains(dishName,like.values)? 1:0;
      }
      return recommend_count_result;
    };
    for (let shop of shops) {
      let s = Object.assign({},{
        shopId: shop.shopId,
        shopName: shop.shopName,
        recommendCount: 0,
        reviewCountAll: shop.reviewCountAll, // 所有评论
        existsCount: 0,  //提及次数
        rate:(0).toFixed(2), //占比
        synthesisScore: shop.shopPower /10, //综合评分
      });
      for (let c of shop.reviewAllDOList){
        s.recommendCount += c.reviewDataVO.reviewData.extInfoList && c.reviewDataVO.reviewData.extInfoList.length > 0? calc_recommend_count(dishName,c.reviewDataVO.reviewData.extInfoList):0;
        s.existsCount += c.reviewDataVO.reviewBody.indexOf(dishName) !== -1 ? 1:0
      }
      if (s.recommendCount > 0 || s.existsCount > 0) {
        s.rate = s.recommendCount === 0 || s. reviewCountAll === 0?(0).toFixed(2): (s.recommendCount  /s.reviewCountAll ).toFixed(2);

        reduces.push(s);
      }
    }
    let flag = recommend_count > 0 || score > 0 || comment_has;
    let flags = [];
    for (let s of reduces){
      if (recommend_count > 0 && score > 0 && comment_has) {
        if ((recommend_count > 0 && s.recommendCount >= recommend_count ) &&(score > 0 && s.synthesisScore >= score ) &&  (comment_has && s.existsCount > 0 )) {
          results.push(s);
          break;
        }
      }else{
        if (recommend_count > 0 ){
          flags.push(s.recommendCount >= recommend_count);
        }
        if (score > 0 ){
          flags.push(s.synthesisScore >= score);
        }
        if (comment_has ){
          flags.push(s.existsCount > 0);
        }
        if (flags.length === 0){
          results.push(s);
        } else{
          console.log(flags.find( q=> q === false)  )
          if (!flags.find( q=> q === false)){
            results.push(s);
          }
        }
      }

    }
    return flag? results: reduces;
  }

  /**
   * 最热店铺分析
   */
  async hotShops(cityName) {
    let shops = [],results = [];
    const cityMapReduce = (cityName) => {
      let cityKey= "chengdu";
      switch (cityName) {
        case "成都":
          cityKey= "chengdu";
          break;
        case "广州":
          cityKey= "guangzhou";
          break;
        case "北京":
          cityKey= "beijing";
          break;
        case "深圳":
          cityKey= "shenzhen";
          break;
      }
      return cityKey;
    }
    if (cityName) {
      shops = shops.concat(await this.ctx.model.Shop.find({ cityName: cityMapReduce(cityName) }));
    }else{
      shops = shops.concat(await this.ctx.model.Shop.find({}));
    }
    // 上月
    const last_month = (current_month) => current_month == 1? 12:current_month -1;
    // 当月
    const this_month = () => new Date(Date.now()).getMonth() + 1;
    const calc_quality_comments_count = ( m, comments ) => {
      let quality_comments_count = 0;
      if (comments && comments.length > 0 ){
        for(let c of comments){
          if (new Date(c.reviewDataVO.addTime).getMonth() + 1 == m){
            quality_comments_count += 1;
          }
        }
      }
      return quality_comments_count;
    };
    if (shops && shops.length > 0 ){
      for (let shop of shops){
        if (shop && shop.reviewAllDOList && shop.reviewAllDOList.length > 0) {
          let s = {
            shopName: shop.shopName,
            shopId: shop.shopId
          }
          s.last_month_coments_count = calc_quality_comments_count(last_month(this_month()) ,shop.reviewAllDOList);//上月评论数
          s.last_month_coments_rank = 0; // 排名
          s.this_month_coments_count = calc_quality_comments_count( this_month() ,shop.reviewAllDOList);//本月评论数
          s.this_month_coments_increase_count = s.this_month_coments_count - s.last_month_coments_count; //本月评论增加数量
          s.this_month_coments_increase_rate = s.this_month_coments_increase_count === 0 || s.last_month_coments_count === 0? 0 : (s.this_month_coments_increase_count  / s.last_month_coments_count).toFixed(2) ; //本月评论增加数量
          s.this_month_coments_increase_rate_rank = 0;
          results.push(s)
        }
      }
    }
    let sorted_by_last_month_comment_result = results.sort((a,b) => a.last_month_coments_count - b.last_month_coments_count);
    let sorted_by_last_month_comment_rate_result = results.sort((a,b) => a.this_month_coments_increase_rate - b.this_month_coments_increase_rate);
    // calc rank
    for (let s of results){
      s.last_month_coments_rank = sorted_by_last_month_comment_result.findIndex( q => q.shopId === s.shopId) + 1;
      s.this_month_coments_increase_rate_rank = sorted_by_last_month_comment_rate_result.findIndex(q => q.shopId === s.shopId) + 1;
    }
    return results;
  }
  /** 
   * 热门美食分类
  */
  async hotFoodCategories(categoryName) {
    let that = this,hotFoodCategories = [];
    if (categoryName) {
      hotFoodCategories = hotFoodCategories.concat(await this.ctx.model.Foodcategory.find({categoryName:categoryName}));
    }else{
      hotFoodCategories = hotFoodCategories.concat(await this.ctx.model.Foodcategory.find({}));
    }
    // 上月
    const last_month = (current_month) => current_month == 1? 12:current_month -1;
    // 当月
    const this_month = () => new Date(Date.now()).getMonth() + 1;
    const calc_quality_comments_count = ( m, comments ) => {
      let quality_comments_count = 0;
      if (comments && comments.length > 0 ){
        for(let c of comments){
          if (new Date(c.reviewDataVO.addTime).getMonth() + 1 == m){
            quality_comments_count += 1;
          }
        }
      }
      return quality_comments_count;
    };

    let shops = await this.ctx.model.Shop.find({});
    let results = [];
    for (let foodCategory of hotFoodCategories) {        
      let obj = {
        categoryName:foodCategory.categoryName,
        last_month_coments_count:0,
        this_month_coments_count:0,
        coments_diff:0,
        coments_increase_rate:0,
        coments_increase_rate_rank:0,
      };
      for (const shop of shops) {        
        if (shop.mainCategoryName.indexOf(foodCategory.categoryName) !== -1) {          
          obj.last_month_coments_count += calc_quality_comments_count(last_month(this_month()),shop.reviewAllDOList)
          obj.this_month_coments_count += calc_quality_comments_count(this_month(),shop.reviewAllDOList)
        }
      }
      results.push(obj)
    }
    let sorted_by_diff_results = results.sort((a,b) => a.coments_increase_rate - b.coments_increase_rate);
    for (let r of results){
      r.coments_diff = r.this_month_coments_count - r.last_month_coments_count;
      r.coments_increase_rate = r.coments_diff === 0 || r.last_month_coments_count === 0? 0: (r.coments_diff / r.last_month_coments_count).toFixed(2);
      r.coments_increase_rate_rank = sorted_by_diff_results.findIndex( q => q.categoryName === r.categoryName) + 1;
    }
    return results;
  }
  /**
   *用户级别分析
   */
  async userLevelAnalysis(){
    let results = [];
    let shops = await this.ctx.model.Shop.find({})
    let sum = 0;
    for (let shop of shops) {    
      if (shop && shop.reviewAllDOList && shop.reviewAllDOList.length > 0) {
        for (let review of shop.reviewAllDOList) {
          if (review.reviewDataVO.expenseInfoList && review.reviewDataVO.expenseInfoList.length > 0 && review.reviewDataVO.expenseInfoList[0].value > 0) {
            results.push({
              vipLevel: review.vipLevel + 1,
              userid: review.reviewDataVO.userId,
              expenseInfoList: review.reviewDataVO.expenseInfoList
            }) 
            sum += review.reviewDataVO.expenseInfoList[0].value
          } 
        }  
      }
    }
    console.info(results,'results')

    let reduce = [];  
    let lv1 = [],lv2 = [],lv3 = [],lv4 = [],lv5 = [];
    for (const data of results) {
      switch (data.vipLevel) {
        case 1:
          lv1.push(data.expenseInfoList[0].value)
          break;
        case 2:
          lv2.push(data.expenseInfoList[0].value)
          break;
        case 3:
          lv3.push(data.expenseInfoList[0].value)
          break;
        case 4:        
          lv4.push(data.expenseInfoList[0].value)
          break;
        case 5:
          lv5.push(data.expenseInfoList[0].value)
          break; 
        default:
          break;
      }  
    }
 
    reduce.push({
      vipLevel: 1,
      avgAmount: (lv1.reduce((total, amount) => total + amount) / lv1.length).toFixed(2),
      percentage: (lv1.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100,
      percentage_display: `${(lv1.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100}%`
    })

    reduce.push({
      vipLevel: 2,
      avgAmount: (lv2.reduce((total, amount) => total + amount) / lv1.length).toFixed(2),
      percentage: (lv2.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100,
      percentage_display: `${(lv2.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100}%`
    })
    reduce.push({
      vipLevel: 3,
      avgAmount: (lv3.reduce((total, amount) => total + amount) / lv1.length).toFixed(2),
      percentage: (lv3.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100,
      percentage_display: `${(lv3.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100}%`
    })
    reduce.push({
      vipLevel: 4,
      avgAmount: (lv4.reduce((total, amount) => total + amount) / lv1.length).toFixed(2),
      percentage: (lv4.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100,
      percentage_display: `${(lv4.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100}%`
    })
    reduce.push({
      vipLevel: 5,
      avgAmount: (lv5.reduce((total, amount) => total + amount) / lv1.length).toFixed(2),
      percentage: (lv5.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100,
      percentage_display: `${(lv5.reduce((total, amount) => total + amount) / sum).toFixed(2) * 100}%`
    })
    return reduce;
  } 

  /**
   * 用餐时间分析
   */
  async dineTimeAnalysis(shopId){
    let results = [],shops = [];
    if (shopId) { 
      shops = shops.concat(await this.ctx.model.Shop.find({ shopId: shopId }));
    }else{
      shops = shops.concat(await this.ctx.model.Shop.find({}));
    }
    console.log(shops)
    for (let shop of shops) {      
      let computed = {
        shopId:shop.shopName,
        breakfastCommentCount:0,
        lunchCommentCount:0,
        pmTeaCommentCount:0,
        dinerCommentCount:0,
        nightCommentCount:0,
        totalCommentCount:0,
        metrics:0,
      }
      if (shop && shop.reviewAllDOList && shop.reviewAllDOList.length > 0) {
        for (let review of shop.reviewAllDOList) {
          var hours = new Date(review.reviewDataVO.addTime).getHours();
          console.log(hours, 'hours')
          let debug_info = ''
          //早餐
          if (hours >= 6 && hours <= 11) {
            computed.breakfastCommentCount += 1;
            debug_info = '早餐'
          }
          //午餐
          if (hours >= 11 && hours <= 13) {
            computed.lunchCommentCount += 1;
            debug_info = '午餐'
          }
          //下午茶
          if (hours >= 15 && hours <= 17) {
            computed.pmTeaCommentCount += 1;
            debug_info = '下午茶'
          }
          //晚餐
          if (hours >= 17 && hours <= 19) {
            computed.dinerCommentCount += 1;
            debug_info = '晚餐'
          }
          //夜宵
          if (hours >= 19 && hours <= 24 && hours <= 6) {
            computed.nightCommentCount += 1;
            debug_info = '夜宵'
          }
          computed.totalCommentCount = computed.breakfastCommentCount + computed.lunchCommentCount + computed.pmTeaCommentCount + computed.dinerCommentCount + computed.nightCommentCount
          console.info(debug_info)
        }
      } 
      results.push(computed);
    }
    // console.log(shops)
    return results;
  }


  /**
   * 优质点评商家
   * @param cityName
   * @param pic_len
   * @param comment_len
   * @returns {Promise<Array>}
   */
  async qualityShopsAnalysis(cityName,pic_len,comment_len){
    let shops = [],quality_shops = [];
    const cityMapReduce = (cityName) => {
      let cityKey= "chengdu";
      switch (cityName) {
        case "成都":
          cityKey= "chengdu";
          break;
        case "广州":
          cityKey= "guangzhou";
          break;
        case "北京":
          cityKey= "beijing";
          break;
        case "深圳":
          cityKey= "shenzhen";
          break;
      }
      return cityKey;
    }
    if (cityName) {
      shops = shops.concat(await this.ctx.model.Shop.find({ cityName: cityMapReduce(cityName) }));
    }else{
      shops = shops.concat(await this.ctx.model.Shop.find({}));
    }
    /**
     *
     * 计算说明：
     *   总评论数是读取出来的，跟时间有关系。优质评论是这样计算的，该条评论的内容在100字以上，附有2张图，平均分在8分以上，就是优质评论，然后计算本月跟次月的占比。
     *
     */
    const calc_quality_comments_count = ( m, comments ) => {

      console.info(`calc_quality_comments_count by month: ${m}   comments len : ${comments.length}`)

      let quality_comments_count = 0;
      if (comments && comments.length > 0 ){
        for(let c of comments){
          if (new Date(c.reviewDataVO.addTime).getMonth() + 1 == m &&  c.reviewDataVO.reviewBodyLength >= comment_len && c.picList && c.picList.length >= pic_len && c.reviewDataVO.reviewData.star >= 40){
            quality_comments_count += 1;
          }
        }
      }
      return quality_comments_count;
    };
    // 上月
    const last_month = (current_month) => current_month == 1? 12:current_month -1;
    // 当月
    const this_month = () => new Date(Date.now()).getMonth() + 1;

    if (shops && shops.length > 0 ){
      for (let shop of shops){
        if (shop && shop.reviewAllDOList && shop.reviewAllDOList.length > 0) {
          let s = {
            shopName: shop.shopName
          }
          s.last_month_total_coments_count = shop.reviewCountAll;
          s.last_month_quality_coments_count = calc_quality_comments_count( last_month(this_month()) ,shop.reviewAllDOList);//上月优质评论数
          s.last_month_rate =s.last_month_total_coments_count === 0? 0  : (s.last_month_quality_coments_count / s.last_month_total_coments_count).toFixed(2)
          //优上月质评论占比
          s.this_month_total_coments_count = shop.reviewCountPic;
          s.this_month_quality_coments_count = calc_quality_comments_count( this_month() ,shop.reviewAllDOList);//上月优质评论数
          s.this_month_rate =  s.this_month_total_coments_count === 0? 0  : (s.this_month_quality_coments_count / s.this_month_total_coments_count).toFixed(2)
          s.growth_rate = s.last_month_quality_coments_count === 0 || s.this_month_quality_coments_count === 0? 0 :  ((s.this_month_quality_coments_count - s.last_month_quality_coments_count) / s.last_month_quality_coments_count).toFixed(2);
          quality_shops.push(s)
        }
      }
    }
    return quality_shops;
  }


  /**
   * 商圈消费分析
   * @param cityName
   * @returns {Promise<void>}
   */
  async businessAnalysis(cityName){
    let business = [],shops=[];
    const cityMapReduce = (cityName) => {
      let cityKey= "chengdu";
      switch (cityName) {
        case "成都":
          cityKey= "chengdu";
          break;
        case "广州":
          cityKey= "guangzhou";
          break;
        case "北京":
          cityKey= "beijing";
          break;
        case "深圳":
          cityKey= "shenzhen";
          break;
      }
      return cityKey;
    }
    if (cityName) {
      shops = shops.concat(await this.ctx.model.Shop.find({ cityName: cityMapReduce(cityName) }));
    }else{
      shops = shops.concat(await this.ctx.model.Shop.find({}));
    }
    // get bussions
    for (let shop of shops){
      if (shop.mainRegionName === '')
        continue;
      let bussion = business.find(q => q.business_name === shop.mainRegionName)
      if (!bussion) {
        business.push({
          business_name: shop.mainRegionName,
          shop_count: 1,
          shops: [shop],
          last_month_avg_price:0,
          this_month_avg_price:0,
          //(本月人均 - 上月人均）/上月人均
          growth_rate: 0
        })
      }else{
        bussion.shop_count = bussion.shop_count + 1;
        bussion.shops.push(shop);
      }
    }

    /**
     * 计算说明：
      获取商圈ID，根据商圈ID的店铺的人均消费，来计算这个商圈的消费平均值：例如检索到这个商圈有2个店铺，店铺A、B、C共有5条评论，就把这5的人均消费全部加起来除以5，即可。
     *
     */

    const sum_total_price = (comments) => {
      let totalPrice = 0;
      for (let c of comments){
        totalPrice += c.reviewDataV0.reviewData.avgPrice;
      }
      return totalPrice;
    }
    const calc_last_month = (current_month) => current_month == 1? 12:current_month -1;
    // calc last month avg price
    const calc_comments_by_month = ( m, comments ) => {
      let results = [],totalPrice = 0;
      for (let c of comments) {
        console.info(new Date(c.reviewDataVO.addTime),new Date(c.reviewDataVO.addTime).getMonth() + 1 );
        if (new Date(c.reviewDataVO.addTime).getMonth() + 1 == m) {
          if ( c.reviewDataVO.reviewData.avgPrice &&  +c.reviewDataVO.reviewData.avgPrice > 0){
            results.push(c)
            totalPrice +=  parseFloat(c.reviewDataVO.reviewData.avgPrice)
          }
        }
      }
      return {results,totalPrice};
    }
    const calc_last_month_avg_price = (busines) => {
      let totalPersonalCount = 0,totalPirce = 0;
      if (busines && busines.shops.length > 0 ){
        for (let s of busines.shops){
          let {results,totalPrice} = calc_comments_by_month( calc_last_month( this_month() ), s.reviewAllDOList);
          totalPersonalCount += results.length
          totalPirce +=  totalPrice;
        }
      }
      return totalPersonalCount === 0 ? 0:  Math.abs((totalPirce / totalPersonalCount).toFixed(2)) ;
    }
    const this_month = () => new Date(Date.now()).getMonth() + 1;
    // calc this month avg price
    const calc_this_month_avg_price = (bussiones) => {
      let totalPersonalCount = 0,totalPirce = 0;
      if (bussiones && bussiones.shops.length > 0 ){
        for (let s of bussiones.shops){
          let {results,totalPrice} = calc_comments_by_month( this_month(), s.reviewAllDOList);
          totalPersonalCount += results.length
          totalPirce +=  totalPrice;
        }
      }
      console.info(`business_name : ${bussiones.business_name}`)
      console.info(`shops len : ${bussiones.shops.length}`)
      console.info(`totalPersonalCount : ${totalPersonalCount}`)
      console.info(`totalPirce : ${totalPirce}`)
      return totalPersonalCount === 0 ? 0: Math.abs((totalPirce / totalPersonalCount).toFixed(2)) ;
    }
    console.log(` business len : ${business.length} `)
    for (let b of business){
      b.last_month_avg_price = isNaN(calc_last_month_avg_price(b)) ? 0:calc_last_month_avg_price(b).toFixed(2);
      b.this_month_avg_price = isNaN(calc_this_month_avg_price(b))? 0:calc_this_month_avg_price(b).toFixed(2);
      //(本月人均 - 上月人均）/上月人均
      b.growth_rate = Math.abs(b.last_month_avg_price === 0 || b.this_month_avg_price ===  0? 0: isNaN(((b.this_month_avg_price - b.last_month_avg_price ) / b.last_month_avg_price).toFixed(2))?0:((b.this_month_avg_price - b.last_month_avg_price ) / b.last_month_avg_price).toFixed(2)) ;
      delete b.shops;
    }
    return business;
  }
}

module.exports = AnalysisService;
